package org.scnb.es;

import main.firefox.StartDrifting;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class RestClientUtils {
    /**
     * 高阶Rest Client
     */
    private RestHighLevelClient client = null;
    /**
     * 低阶Rest Client
     */
    private RestClient restClient = null;

    /**
     * 这里使用饿汉单例模式创建RestHighLevelClient
     */
    public RestClientUtils() {
        if (client == null) {
            synchronized (RestHighLevelClient.class) {
                if (client == null) {
                    client = getClient();
                }
            }
        }
    }

    private RestHighLevelClient getClient() {
        RestHighLevelClient client = null;

        try {
            client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("127.0.0.1", 9200, "http")
                    )
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

    private RestClient getRestClient() {
        RestClient client = null;

        try {
            client = RestClient.builder(
                    new HttpHost("127.0.0.1", 9200, "http")
            ).build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

    public void closeClient() {
        try {
            if (client != null) {
                client.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * document API 主要是些简单的增删改查操作
     */
    public void documentAPI() {
        //...
    }

    /**
     * Search API 主要是些复杂查询操作
     */
    public void searchAPI() {
        //...
    }

    public Map<String, Object> searchReportSemanticVector(String bug_id) throws IOException {

        //使用SearchSourceBuilder查询指定字段
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("bug_id", bug_id));
        sourceBuilder.from(0);
        sourceBuilder.size(500000);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        sourceBuilder.fetchSource(new String[]{"bug_id", "summary_vector_split_tri", "desc_vector_split_tri"}, null);
        SearchRequest searchRequest2 = new SearchRequest();
        //index 数据库
        searchRequest2.indices(StartDrifting.esIndexName);
        searchRequest2.source(sourceBuilder);

        //同步执行
        SearchResponse searchResponse = client.search(searchRequest2, RequestOptions.DEFAULT);

        //SearchResponse
        RestStatus status = searchResponse.status();
        for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
            System.out.println("RestClientUtils搜索出现了一些错误 + " + failure.toString());
        }

        Map<String, Object> sourceAsMap = null;

        //Retrieving SearchHits 获取结果数据
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) {
            sourceAsMap = hit.getSourceAsMap();
        }
        return sourceAsMap;
    }

    public void search() throws IOException {
        //match all query 查询所有数据
//        SearchRequest searchRequest = new SearchRequest();
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//        searchRequest.source(searchSourceBuilder);

        //使用SearchSourceBuilder查询指定字段
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("bug_id", "100"));
        sourceBuilder.from(0);
        sourceBuilder.size(1000000);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        sourceBuilder.fetchSource("bug_id", null);
        SearchRequest searchRequest2 = new SearchRequest();
        //index 数据库
        searchRequest2.indices("openoffice5");
        searchRequest2.source(sourceBuilder);

        //Building queries
        //One way, QueryBuilder can be created using its constructor 使用QueryBuilder的构造函数
//        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
//        matchQueryBuilder.fuzziness(Fuzziness.AUTO);
//        matchQueryBuilder.prefixLength(3);
//        matchQueryBuilder.maxExpansions(10);
        //Two way, QueryBuilder objects can also be created using the QueryBuilders utility class. 直接使用matchQuery
//        QueryBuilder matchQueryBuilder1 = matchQuery("user", "kimchy")
//                                                       .fuzziness(Fuzziness.AUTO)
//                                                       .prefixLength(3)
//                                                       .maxExpansions(10);
//
//        searchSourceBuilder.query(matchQueryBuilder1);

        //Specifying Sorting 指定排序
//        sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//        sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));

        //Source filtering, turn off _source retrieval completely
//        sourceBuilder.fetchSource(false);
//        //an array of one or more wildcard patterns to control which fields get included or excluded in a more fine grained way
//        String[] includeFields = new String[] {"title", "user", "innerObject.*"};
//        String[] excludeFields = new String[] {"_type"};
//        sourceBuilder.fetchSource(includeFields, excludeFields);
//
//        //Requesting Aggregations
//        SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
//        TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
//                .field("company.keyword");
//        aggregation.subAggregation(AggregationBuilders.avg("average_age")
//                .field("age"));
//        searchSourceBuilder2.aggregation(aggregation);
//
//        //Requesting Suggestions
//        SearchSourceBuilder searchSourceBuilder3 = new SearchSourceBuilder();
//        SuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion("user").text("kmichy");
//        SuggestBuilder suggestBuilder = new SuggestBuilder();
//        suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
//        searchSourceBuilder3.suggest(suggestBuilder);

        //同步执行
        SearchResponse searchResponse = client.search(searchRequest2, RequestOptions.DEFAULT);

//        //异步执行
//        ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
//            public void onResponse(SearchResponse searchResponse) {
//
//            }
//
//            public void onFailure(Exception e) {
//
//            }
//        };

        //异步执行 listener参考index的——已经改好了，上面
//        client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);

        //SearchResponse
        RestStatus status = searchResponse.status();
        for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
            // failures should be handled here
        }

        //Retrieving SearchHits 获取结果数据
        SearchHits hits = searchResponse.getHits();
        long totalHits = hits.getTotalHits();
        float maxScore = hits.getMaxScore();
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) {
            // do something with the SearchHit
            String index = hit.getIndex();
            String type = hit.getType();
            String id = hit.getId();
            float score = hit.getScore();

            // 对结果的处理方式1：转成字符串形式
            String sourceAsString = hit.getSourceAsString();
            // 对结果的处理方式2：转成map形式
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String documentTitle = (String) sourceAsMap.get("title");
            List<Object> users = (List<Object>) sourceAsMap.get("user");
            Map<String, Object> innerObject =
                    (Map<String, Object>) sourceAsMap.get("innerObject");
        }

        //Retrieving Aggregations
//        Aggregations aggregations = searchResponse.getAggregations();
//        Terms byCompanyAggregation = aggregations.get("by_company");
//        Terms.Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
//        Avg averageAge = elasticBucket.getAggregations().get("average_age");
//        double avg = averageAge.getValue();
//
//        Range range = aggregations.get("by_company");
//        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
//        Terms companyAggregation = (Terms) aggregationMap.get("by_company");
//
//        List<Aggregation> aggregationList = aggregations.asList();
//        for (Aggregation agg : aggregations) {
//            String type = agg.getType();
//            if (type.equals(TermsAggregationBuilder.NAME)) {
//                Terms.Bucket elasticBucket1 = ((Terms) agg).getBucketByKey("Elastic");
//                long numberOfDocs = elasticBucket1.getDocCount();
//            }
//        }
//
//        //Retrieving Suggestions
//        Suggest suggest = searchResponse.getSuggest();
//        TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
//        for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
//            for (TermSuggestion.Entry.Option option : entry) {
//                String suggestText = option.getText().string();
//            }
//        }
    }

}
